package com.cloud.punish.tasklist.service.impl;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.cloud.punish.common.context.HumanSession;
import com.cloud.punish.common.utils.SessionHelper;
import com.cloud.punish.tasklist.bean.TaskListTabMenuBean;
import com.cloud.punish.tasklist.entity.*;
import com.cloud.punish.tasklist.mapper.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cloud.punish.common.result.QkIcon;
import com.cloud.punish.common.result.QkTreeNode;
import com.cloud.punish.tasklist.bean.MenuTabAuthority;
import com.cloud.punish.tasklist.bean.Part;
import com.cloud.punish.tasklist.bean.TabMenuHeader;
import com.cloud.punish.tasklist.service.TaskListTabService;

import tk.mybatis.mapper.entity.Example;

@Service
@Transactional
public class TaskListTabServiceImpl implements TaskListTabService {
    @Autowired
    private TaskListTabGroupMapper taskListTabGroupMapper;
    @Autowired
    private TaskListTabMenuMapper taskListTabMenuMapper;
    @Autowired
    private TaskListTabMapper taskListTabMapper;
    @Autowired
    private TaskListTabPartMapper tabPartMapper;

    @Autowired
    private TaskListTabMenuPartMapper taskListTabMenuPartMapper;
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<QkTreeNode> listTree() {
        Example grpExample = new Example(TaskListTabGroup.class);
        Example.Criteria grpCriteria = grpExample.createCriteria();
        grpCriteria.andEqualTo("deleteFlag", 0);
        grpExample.orderBy("displayOrder").asc();
        List<TaskListTabGroup> groups = taskListTabGroupMapper.selectByExample(grpExample);
        Example tabExample = new Example(TaskListTab.class);
        Example.Criteria tabCriteria = tabExample.createCriteria();
        tabCriteria.andEqualTo("deleteFlag", 0);
        tabExample.orderBy("displayOrder").asc();
        List<TaskListTab> tabs = taskListTabMapper.selectByExample(tabExample);
        List<QkTreeNode> nodes = new ArrayList<QkTreeNode>();
        for (TaskListTabGroup group : groups) {
            QkTreeNode grpNode = new QkTreeNode("grp_" + group.getGroupId(), group.getGroupName());
            grpNode.setCollapsedIcon(QkIcon.FA_FOLDER);
            grpNode.setExpandedIcon(QkIcon.FA_FOLDER_OPEN);
            grpNode.setRootFlag(true);
            grpNode.setSelectable(true);
            grpNode.setExpanded(true);
            for (TaskListTab tab : tabs) {
                if (tab.getGroupId().equals(group.getGroupId())) {
                    QkTreeNode menuNode = new QkTreeNode(tab.getTabId(), tab.getTabName());
                    menuNode.setSeniorId("grp_" + group.getGroupId());
                    menuNode.setSelectable(true);
                    menuNode.setLeaf(true);
                    menuNode.setIcon(QkIcon.FA_LAPTOP);
                    grpNode.getChildren().add(menuNode);
                }
            }
            nodes.add(grpNode);
        }
        return nodes;
    }

    @Override
    public void saveUpdatePartAuth(List<MenuTabAuthority> parts, long actDefId, long taskListId) {
        Example exp = new Example(TaskListTabPart.class);
        Example.Criteria criteria = exp.createCriteria();
        criteria.andEqualTo("taskListId", taskListId);
        criteria.andEqualTo("actDefId", actDefId);
        tabPartMapper.deleteByExample(exp);
        List<TaskListTabPart> partTabs = new ArrayList<TaskListTabPart>();
        for (MenuTabAuthority part : parts) {
            TaskListTabPart tPart = new TaskListTabPart();
            tPart.setTaskListId(taskListId);
            tPart.setActDefId(actDefId);
            tPart.setPartId(part.getPartId());
            tPart.setTabId(part.getMenuTabId());
            tPart.setAuthCode(part.getCode());
            partTabs.add(tPart);
        }
        final List<TaskListTabPart> pts = partTabs;
        jdbcTemplate.batchUpdate(
                "insert into tab_part(task_list_id, act_def_id, part_id, tab_id, auth_code) values (?, ?, ?, ?, ?)",
                new BatchPreparedStatementSetter() {
                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        TaskListTabPart p = pts.get(i);
                        ps.setLong(1, p.getTaskListId());
                        ps.setLong(2, p.getActDefId());
                        ps.setLong(3, p.getPartId());
                        ps.setLong(4, p.getTabId());
                        ps.setInt(5, p.getAuthCode());
                    }

                    @Override
                    public int getBatchSize() {
                        return pts.size();
                    }
                });

    }

    @Override
    public List<Part> listPartAuthority(long taskListId, long actDefId, List<Part> parts) {
        Example example = new Example(TaskListTab.class);
        example.orderBy("displayOrder").asc();
        List<TaskListTab> tabs = taskListTabMapper.selectByExample(example);
        // 先设置所有的tab为默认权限
        for (Part p : parts) {
            for (TaskListTab tab : tabs) {
                p.getAuths().put(tab.getTabId(), tab.getDefaultAuth());
            }
        }
        // 设置所有参与者配置的权限
        Example tabPartsExample = new Example(TaskListTabPart.class);
        Example.Criteria tpCriteria = tabPartsExample.createCriteria();
        tpCriteria.andEqualTo("taskListId", taskListId);
        tpCriteria.andEqualTo("actDefId", actDefId);
        List<TaskListTabPart> tabParts = tabPartMapper.selectByExample(tabPartsExample);

        // 配置权限覆盖默认权限
        for (Part p : parts) {
            Map<Long, Integer> auths = p.getAuths();
            for (TaskListTabPart tp : tabParts) {
                if (tp.getPartId().equals(p.getPartId())) {
                    auths.put(tp.getTabId(), tp.getAuthCode());
                }
            }
        }
        return parts;
    }

    @Override
    public List<TaskListTab> listTaskListPartByPart(long taskListId, long actDefId, List<Long> parts) {
        Example example = new Example(TaskListTabPart.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("taskListId", taskListId);
        criteria.andEqualTo("actDefId", actDefId);
        criteria.andIn("partId", parts);
        List<TaskListTabPart> tabParts = tabPartMapper.selectByExample(example);
        List<Long> tabIds = new ArrayList<Long>();
        for (TaskListTabPart tp : tabParts) {
            tabIds.add(tp.getTabId());
        }
        if (tabIds.size() > 0) {
            Example tabExample = new Example(TaskListTab.class);
            Example.Criteria tabCriteria = tabExample.createCriteria();
            tabCriteria.andIn("tabId", tabIds);
            tabExample.orderBy("displayOrder");
            return taskListTabMapper.selectByExample(tabExample);
        }
        return null;
    }

    @Override
    public TaskListTabGroup saveUpdateGroup(TaskListTabGroup group) {
        if (null == group.getGroupId() || 0 == group.getGroupId()) {
            group.setDeleteFlag(0);
            taskListTabGroupMapper.insert(group);
        } else {
            group.setDeleteFlag(0);
            taskListTabGroupMapper.updateByPrimaryKey(group);
        }
        return group;
    }

    @Override
    public void deleteGroup(long groupId) {
        TaskListTabGroup group = taskListTabGroupMapper.selectByPrimaryKey(groupId);
        group.setDeleteFlag(1);
        taskListTabGroupMapper.updateByPrimaryKey(group);
    }

    @Override
    public TaskListTab saveUpdateTaskListTab(TaskListTab tab) {
        if (null == tab.getTabId() || 0 == tab.getTabId()) {
            tab.setDeleteFlag(0);
            taskListTabMapper.insert(tab);
        } else {
            tab.setDeleteFlag(0);
            taskListTabMapper.updateByPrimaryKey(tab);
        }
        return tab;
    }

    @Override
    public long deleteTab(long tabId) {
        TaskListTab tab = taskListTabMapper.selectByPrimaryKey(tabId);
        tab.setDeleteFlag(1);
        taskListTabMapper.updateByPrimaryKey(tab);
        return tabId;
    }

    @Override
    public TaskListTab loadTab(long tabId) {
        return taskListTabMapper.selectByPrimaryKey(tabId);
    }

    @Override
    public List<TaskListTab> getTabList(Long taskListId, Long actDefId, Long partId) {

        String sql = "SELECT a.*,case when b.auth_code is NULL then 1 ELSE b.auth_code end as selected from task_list_tab a\n" +
                "LEFT JOIN (SELECT tab_id,auth_code FROM task_list_tab_part WHERE task_list_id = ? and act_def_id = ? and part_id = ?) b \n" +
                "on a.tab_id = b.tab_id  ";
        List<TaskListTab> taskListTabs = jdbcTemplate.query(sql, new BeanPropertyRowMapper<TaskListTab>(TaskListTab.class), taskListId, actDefId, partId);

        return taskListTabs;
    }

    @Override
    public List<TaskListTabMenu> getTabMenuList(Long tabId, Long taskListId, Long actDefId, Long partId) {
        String sql = "SELECT a.*,case when b.auth_code is NULL then 1 ELSE b.auth_code end as selected from (select * from task_list_tab_menu where tab_id = ?) a\n" +
                "LEFT JOIN (SELECT menu_id,auth_code FROM task_list_tab_menu_part WHERE task_list_id = ? and act_def_id = ? and part_id = ? and tab_id = ?) b \n" +
                "on a.menu_id = b.menu_id  ";
        List<TaskListTabMenu> taskListTabMenus = jdbcTemplate.query(sql, new BeanPropertyRowMapper<TaskListTabMenu>(TaskListTabMenu.class), tabId, taskListId, actDefId, partId, tabId);

        return taskListTabMenus;
    }

    @Override
    public void saveTabPart(TaskListTabMenuBean param) {

        List<TaskListTab> taskListTabs = JSON.parseArray(param.getTabString(), TaskListTab.class);

        Example example = new Example(TaskListTabPart.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("taskListId", param.getTaskListId());
        criteria.andEqualTo("actDefId", param.getActDefId());
        criteria.andEqualTo("partId", param.getPartId());
        tabPartMapper.deleteByExample(example);



        jdbcTemplate.batchUpdate(
                "insert into task_list_tab_part(task_list_id, act_def_id, part_id, tab_id, auth_code) values (?, ?, ?, ?, ?)",
                new BatchPreparedStatementSetter() {
                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        TaskListTab p = taskListTabs.get(i);
                        ps.setLong(1, param.getTaskListId());
                        ps.setLong(2, param.getActDefId());
                        ps.setLong(3, param.getPartId());
                        ps.setLong(4, p.getTabId());
                        ps.setInt(5, p.getSelected());
                    }

                    @Override
                    public int getBatchSize() {
                        return taskListTabs.size();
                    }
                });

    }

    @Override
    public void saveTabPartMenu(TaskListTabMenuBean param) {
        List<TaskListTabMenu> taskListTabMenus = JSON.parseArray(param.getTabMenuString(), TaskListTabMenu.class);

        Example example = new Example(TaskListTabMenuPart.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("taskListId", param.getTaskListId());
        criteria.andEqualTo("actDefId", param.getActDefId());
        criteria.andEqualTo("partId", param.getPartId());
        criteria.andEqualTo("tabId", param.getTabId());
        taskListTabMenuPartMapper.deleteByExample(example);

        jdbcTemplate.batchUpdate(
                "insert into task_list_tab_menu_part(task_list_id, act_def_id, part_id, tab_id,menu_id, auth_code) values (?, ?, ?, ?, ?, ?)",
                new BatchPreparedStatementSetter() {
                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        TaskListTabMenu p = taskListTabMenus.get(i);
                        ps.setLong(1, param.getTaskListId());
                        ps.setLong(2, param.getActDefId());
                        ps.setLong(3, param.getPartId());
                        ps.setLong(4, param.getTabId());
                        ps.setLong(5, p.getMenuId());
                        ps.setInt(6, p.getSelected());
                    }

                    @Override
                    public int getBatchSize() {
                        return taskListTabMenus.size();
                    }
                });
    }

    @Override
    public List<TaskListTab> loadTaskListTabs(Long taskListId, Long actDefId) {
        HumanSession humanSession = SessionHelper.get();
        List<Long> parts = humanSession.getParts();
        String partFilter = StringUtils.join(parts, ",");


        String sql = "SELECT a.*,case when b.auth_code is NULL then 1 ELSE b.auth_code end as selected from task_list_tab a\n" +
                "LEFT JOIN (SELECT tab_id,auth_code FROM task_list_tab_part WHERE task_list_id = ? and act_def_id = ? and part_id in ( "+partFilter+" )) b \n" +
                "on a.tab_id = b.tab_id  ";
        List<TaskListTab> taskListTabs = jdbcTemplate.query(sql, new BeanPropertyRowMapper<TaskListTab>(TaskListTab.class), taskListId, actDefId);
        return taskListTabs;
    }

    @Override
    public List<TabMenuHeader> listTaskListTabMenus() {
        Example tabExample = new Example(TaskListTab.class);
        Example.Criteria tabCriteria = tabExample.createCriteria();
        tabCriteria.andEqualTo("deleteFlag", 0);
        tabExample.orderBy("displayOrder");
        List<TaskListTab> tabs = taskListTabMapper.selectByExample(tabExample);

        Example tabMenuExample = new Example(TaskListTabMenu.class);
        tabMenuExample.orderBy("displayOrder");
        List<TaskListTabMenu> tabMenus = taskListTabMenuMapper.selectByExample(tabExample);

        List<TabMenuHeader> result = new ArrayList<TabMenuHeader>();
        for (TaskListTab tab : tabs) {
            TabMenuHeader tabHeader = new TabMenuHeader();
            tabHeader.setId(tab.getTabId());
            tabHeader.setHeader(tab.getTabName());
            for (TaskListTabMenu menu : tabMenus) {
                if (tab.getTabId() == menu.getTabId()) {
                    TabMenuHeader tabMenuHeader = new TabMenuHeader();
                    tabMenuHeader.setId(menu.getMenuId());
                    tabMenuHeader.setHeader(menu.getMenuName());
                    tabMenuHeader.setSeniorId(menu.getTabId());
                    tabHeader.getChildren().add(tabMenuHeader);
                }
            }
            result.add(tabHeader);
        }
        return result;
    }

}
